#include <DHTesp.h>


#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>


DHTesp dht;

#define DHT11_PIN 16
const char* ssid = "autor";
const char* password = "88888888";

//const char* mqtt_server = "192.168.43.168";//服务器的地址
const int port = 61613; //服务器端口号
IPAddress mqtt_server ;
WiFiClient espClient;
PubSubClient client(espClient);
int hum = 66 , tem = 80 ;
int tag = 0;
DynamicJsonDocument doc(256);


String IpAddress2String(const IPAddress& ipAddress)
{
  return String(ipAddress[0]) + String(".") + \
         String(ipAddress[1]) + String(".") + \
         String(ipAddress[2]) + String(".") + \
         String(ipAddress[3])  ;
}

void setup_wifi() {//自动连WIFI接入网络
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print("...");
  }
  Serial.print("WIFI is ok\r\n");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("gatewayIP address: ");
  Serial.println(WiFi.gatewayIP());
  mqtt_server = WiFi.gatewayIP() ;
}

char* getchars(byte* data , int len) {
  char out[len] ;
  int i = 0 ;
  for ( ; i < len ; i++) {
    out[i] = *(data);
    data ++ ;
  }
  return out;
}

void sendMsg() {
  delay(100);
  if (tag == 100) {
    tag = 0;

    //delay(dht.getMinimumSamplingPeriod());
    float humidity = dht.getHumidity();
    float temperature = dht.getTemperature();
    //Serial.print("Temperature = "); //温度
    Serial.println(temperature);
    //Serial.print("Humidity = "); //湿度
    Serial.println(humidity);
    doc["datat"] = temperature ;
    doc["datah"] = humidity ;
    doc["type"] = "sensor";
    String output;
    serializeJson(doc, output);
    Serial.println(output.c_str());
    client.publish("/public/sensor",output.c_str());
    doc.clear();
  }else tag++;
}

void callback(char* topic, byte* payload, unsigned int length) {//用于接收数据
  Serial.println("receive:");
  char* p = (char*)malloc(length);
  // Copy the payload to the new buffer
  memcpy(p, (char *)payload, length);
  p[length] = '\0';  //这边必须加结尾，否则会被认为没有结尾，乱码
  String s = p; //转json的时候要换成String
  deserializeJson(doc, s);
  JsonObject obj = doc.as<JsonObject>();
  int ino = obj["ino"];
  int state = obj["state"];
  pinMode(ino, OUTPUT);
  if (state == 0) {
    digitalWrite(ino, HIGH);
  }
  else if (state == 1) {
    digitalWrite(ino, LOW);
  }

  Serial.println(p);
  // Free the memory
  free(p);
  doc.clear();
}

void reconnect() {//等待，直到连接上服务器
  while (!client.connected()) {//如果没有连接上
    if (client.connect("id890284023", "admin", "123456")) { //接入时的用户名，尽量取一个很不常用的用户名

    } else {
      Serial.print("failed, rc=");//连接失败
      Serial.print(client.state());//重新连接
      Serial.println(" try again in 5 seconds");//延时5秒后重新连接
      delay(5000);
    }
    client.subscribe("/public/control");//接收外来的数据时的intopic
  }
  
}
void setup() {//初始化程序，只运行一遍
  Serial.begin(9600);//设置串口波特率（与烧写用波特率不是一个概念）
  pinMode(DHT11_PIN,OUTPUT);
  digitalWrite(0, HIGH);
  digitalWrite(2, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  setup_wifi();//自动连WIFI接入网络
  client.setServer(mqtt_server, port);//端口号
  client.setCallback(callback); //用于接收服务器接收的数据
  dht.setup(DHT11_PIN, DHTesp::DHT11); // Connect DHT sensor to GPIO 16
  
  //Serial.print("\r\n mqtt is ok \r\n");
}



void loop() {//主循环
  reconnect();//确保连上服务器，否则一直等待。
  client.loop();//MUC接收数据的主循环函数。
  sendMsg();
}
